from rest_framework.views import APIView
from django.shortcuts import HttpResponse
from rest_framework import viewsets, mixins, status
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from utils.permissions import IsOwnerOrReadOnly
from .serializers import ShoppingCartSerializer, ShoppingDetailSerializer, PayInfoSerializer, PayDetailSerializer, \
    UpdatePayStatusSerializer, OncePayInfoSerializer
from .models import ShoppingCart, PayInfo, OrderInfo
import math
from apps.utils.custom_response import CustomPagination
from django.views.generic import View
from django.http import HttpResponse, JsonResponse
import json


class UpdatePayStatus(View):
    def post(self, request):
        data = {
            'code': 200,
            'message': 'success',
            'data': ''
        }
        return JsonResponse(data)


class SuperPayInfoViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.ListModelMixin,
                          mixins.DestroyModelMixin, viewsets.GenericViewSet):
    queryset = PayInfo.objects.all()
    serializer_class = PayInfoSerializer

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        # print(queryset)
        page = self.paginate_queryset(queryset)
        # print(page)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        pageNum = request.query_params.get('pageNum', 1)
        pageSize = request.query_params.get('pageSize', 5)
        serializer = self.get_serializer(queryset, many=True)
        # print(serializer.data)
        start = 0 if int(pageNum) == 1 else int(pageNum) - 1
        s = start * int(pageSize)
        e = (start * int(pageSize)) + int(pageSize)
        print(s, e)
        data = {
            'pageNum': int(pageNum),
            'pageSize': int(pageSize),
            'totalPage': math.ceil(queryset.count() / int(pageSize)),
            'total': queryset.count(),
            'list': serializer.data[s:e]
        }
        return Response({'code': 200, 'message': '操作成功', 'data': data})


class BuyPayInfoViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    authentication_classes = (JSONWebTokenAuthentication,)
    serializer_class = OncePayInfoSerializer

    def perform_create(self, serializer):
        print(serializer)


class PayInfoViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.ListModelMixin,
                     mixins.DestroyModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet):
    """
    订单的创建、取消、删除、查询
    """
    # serializer_class = PayInfoSerializer
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    authentication_classes = (JSONWebTokenAuthentication,)
    pagination_class = CustomPagination
    # 精准查询
    filterset_fields = ['status', 'order_sn']  # 精确查找
    # 不在使用id 而是使用这个字段为主键
    lookup_field = 'order_sn'

    def get_serializer_class(self):
        print(self.action, 'Gage')
        if self.action == 'retrieve':
            return PayDetailSerializer
            # post put delete  patch
        # partial_update
        elif self.action == 'partial_update':
            return UpdatePayStatusSerializer
        return PayInfoSerializer

    # 进行遍历保存
    def perform_create(self, serializer):
        """
        快照  sku spu
        查询中  old表查询
        :param serializer:
        :return:
        """
        # 过滤选中的商品
        shop_cart = ShoppingCart.objects.filter(user=self.request.user).filter(is_select=True)
        if not shop_cart:
            return None
        order = serializer.save()

        # 这个地方 不从购物车数据库中查找
        # 根据传递的数据 进行保存
        for item in shop_cart:
            child_order = OrderInfo()
            child_order.goods = item.goods
            child_order.nums = item.nums
            child_order.pay = order
            child_order.save()
            # 减少库存  暂时不做
            good = item.goods
            good.good_num -= item.nums
            good.save()
            # 逐个删除购物车
            item.delete()
        return order

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        if self.perform_create(serializer):
            headers = self.get_success_headers(serializer.data)
            data = {
                'code': 200,
                'message': 'success',
                'data': serializer.data
            }
            return Response(data, status=status.HTTP_200_OK, headers=headers)
        else:
            data = {
                'code': 1003,
                'message': '购物车为空',
                'data': ''
            }
            return Response(data, status=status.HTTP_200_OK)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        data = {
            'code': 200,
            'message': '订单取消成功',
            'data': ''
        }
        return Response(data, status=status.HTTP_200_OK)

    def perform_destroy(self, instance):
        # 取消订单增加库存
        # 注意逻辑删除
        modify_status = PayInfo.objects.get(order_sn=instance.order_sn)
        modify_status.status = 'USER_CLOSE'
        modify_status.save()

        # is_exist = OrderInfo.objects.filter(pay__order_sn=instance.order_sn)
        # if is_exist:
        #     for item in is_exist:
        #         item.goods.good_num += item.nums
        #         item.goods.save()
        # instance.delete()

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status=status.HTTP_200_OK)

    def get_queryset(self):
        """
        返回鉴权用户的订单
        :return:
        """
        return PayInfo.objects.filter(user=self.request.user).order_by('-add_time')


class ShoppingCartViewSet(viewsets.ModelViewSet):
    # serializer_class = ShoppingCartSerializer
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)  # 需要鉴权
    authentication_classes = (JSONWebTokenAuthentication,)  # 鉴权认证
    lookup_field = 'goods_id'  # 根据 good.id 查询详情
    pagination_class = CustomPagination

    # serializer_class 失效
    # 序列化类校验完成 即可save保存
    def get_serializer_class(self):
        # 查询列表 get
        if self.action == 'list':
            return ShoppingDetailSerializer

        else:
            return ShoppingCartSerializer

    def get_queryset(self):
        return ShoppingCart.objects.filter(user=self.request.user)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status=status.HTTP_200_OK, headers=headers)

    def destroy(self, request, *args, **kwargs):
        """
        删除码  204  delete
        创建 201  create
        查询 200  get
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        instance = self.get_object()
        self.perform_destroy(instance)
        data = {
            'code': 200,
            'message': 'success',
            'data': {}
        }
        return Response(data, status=status.HTTP_200_OK)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        data = {
            'code': 200,
            'message': 'success',
            'data': serializer.data
        }
        return Response(data, status=status.HTTP_200_OK)

    # def partial_update(self, request, pk=None):
    #     serialized = DemoSerializer(request.user, data=request.data, partial=True)
    #     return Response(status=status.HTTP_202_ACCEPTED)


# class AliPayViewSet(APIView):
#     def get(self, request):
#         from utils import handle_django_query_dict
#         # print(type(request.GET), request.GET)
#         print(handle_django_query_dict(request.GET))
#         get_pay_dcit = {}
#         return_data = request.GET.items()
#         for key, item in return_data:
#             get_pay_dcit[key] = item
#         sign = get_pay_dcit.pop('sign', None)
#         # print(get_pay_dcit)
#
#     def post(self, request):
#         pass
from rest_framework.views import APIView
from utils.alipay import AliPay
from shop.settings import private_key, alipay_public_key
from rest_framework.response import Response
from datetime import datetime
from django.shortcuts import redirect


# 这个接收   用fastapi承接
class AliPayViewSet(APIView):
    def get(self, request):
        """
        处理支付宝的return_url返回
        :param request:
        :return:
        """
        processed_dict = {}
        for key, value in request.GET.items():
            processed_dict[key] = value

        sign = processed_dict.pop("sign", None)

        alipay = AliPay(
            appid="2016101000652414",
            app_notify_url="http://139.199.123.96:8000/alipay/return/",
            app_private_key_path=private_key,
            alipay_public_key_path=alipay_public_key,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            debug=True,  # 默认False,
            return_url="http://139.199.123.96:8000/alipay/return/"
        )

        verify_re = alipay.verify(processed_dict, sign)

        if verify_re is True:
            return HttpResponse('支付成功')
            response = redirect("index")
            response.set_cookie("nextPath", "pay", max_age=3)
            return response
        else:
            response = redirect("index")
            return response

    def post(self, request):
        """
        处理支付宝的notify_url
        :param request:
        :return:
        """
        processed_dict = {}
        for key, value in request.POST.items():
            processed_dict[key] = value

        sign = processed_dict.pop("sign", None)

        alipay = AliPay(
            appid="2016101000652414",
            app_notify_url="http://139.199.123.96:8000/alipay/return/",
            app_private_key_path=private_key,
            alipay_public_key_path=alipay_public_key,  # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            debug=True,  # 默认False,
            return_url="http://139.199.123.96:8000/alipay/return/"
        )

        verify_re = alipay.verify(processed_dict, sign)

        if verify_re is True:
            order_sn = processed_dict.get('out_trade_no', None)
            trade_no = processed_dict.get('trade_no', None)
            trade_status = processed_dict.get('trade_status', None)

            existed_orders = PayInfo.objects.filter(order_sn=order_sn)
            for existed_order in existed_orders:
                order_goods = existed_order.goods.all()
                for order_good in order_goods:
                    goods = order_good.goods
                    goods.sold_num += order_good.nums
                    goods.save()

                existed_order.status = trade_status
                existed_order.pay_sn = trade_no
                existed_order.pay_time = datetime.now()
                existed_order.save()

            return Response("success")
